package com.nkzy.controller;

import com.nkzy.pojo.Result;
import com.nkzy.pojo.User;
import com.nkzy.service.UserService;
import com.nkzy.utils.JwtUtil;
import com.nkzy.utils.Md5Util;
import com.nkzy.utils.ThreadLocalUtil;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.URL;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * RestFul API请示常用的方法：
 * 1.get:查看
 * 2.post:注册、登录等凡是与表单相关的操作
 * 3.put:更新
 * 4.delete：删除
 * 5.patch:部分修改
 */
//@Controller:也是控制器的注解，返回值是字符串
@RestController  //这个注册说明类是一个控制器，并且返回值为JSON对象
@RequestMapping("/user")
@Validated
public class UserController {
    //控制器是前端和后端交互的桥梁，在这个类中要编写多个方法（接口）
    @Resource
    private UserService userService;
    //注册的方法
    @PostMapping("/register")
    public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,
                           @Pattern(regexp = "^\\S{5,16}$") String password){
        //对用户名和密码要进行校验：1.在pom中加依赖2.对参数加正则表达式3.类上加上@Validated
        //1.查询用户
        User user = userService.findUserByName(username);
        if(user==null){
            //注册
            userService.register(username,password);
            return Result.success();
        }else{
           //存在
           return Result.error("用户名已被占用");
        }
    }
    //登录的方法
    @PostMapping("/login")
    public Result login(@Pattern(regexp = "^\\S{5,16}$") String username,
                        @Pattern(regexp = "^\\S{5,16}$") String password){
        //1.根据用户名查找用户
        User loginUser = userService.findUserByName(username);
        //2.判断用户是否存在
        if(loginUser==null){//用户不存在
            return Result.error("请注册再登录");
        }
        //3.如果用户存在，需要再判断密码是否一致（因为表中的密码是加密的，甩以需要对传入的密码先加密再对比 ）
        String md5String = Md5Util.getMD5String(password);
        if(md5String.equals(loginUser.getPassword())){
            //相等，说明登录成功
            //生成令牌
            HashMap<String, Object> claims = new HashMap<>();
            claims.put("id",loginUser.getId());
            claims.put("username",loginUser.getUsername());
            String token = JwtUtil.genToken(claims);
            //返回token
            return Result.success(token);
        }
        return Result.error("密码有误，请重新登录");
    }
    //获取用户详细信息的方法
    @GetMapping("/userInfo")
    public Result userInfo(){
        //根据用户名查询用户
        //在拦截器中对token进行了解析，在userInfo()中再次进行解析，代码重复，不可取
        //解决：Java中提供了一个类ThreadLocal,提供线程局部变量。我们可以使用set（）/get()
        //Map<String, Object> map = JwtUtil.parseToken(toke);
        Map<String,Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        User user = userService.findUserByName(username);
        return Result.success(user);
    }
    //更新用户信息
    @PutMapping("/update")
    public Result update(@RequestBody User user){//如果请示参数是JSON对象，我们需要使用@RequestBody，把JSON对象转换成user对象
        //完成更新
        userService.update(user);
        return Result.success();
    }
    //更新用户头像
    @PatchMapping("/updateAvatar")
    public Result updateAvatar(@RequestParam("URL") @URL String avatarUrl){
       // @RequestParam 如果方法形参与请示参数名称不一致，可以使用这个注解完成匹配
        userService.updateAvatar(avatarUrl);
        return Result.success();
    }
    //更新用户密码
    @PatchMapping("/updatePwd")
    public Result updatePwd(@RequestBody Map<String,String> params){
        //1.从map集合中取出三个参数
        String oldPwd = params.get("old_pwd");
        String newPwd = params.get("new_pwd");
        String rePwd = params.get("re_pwd");
        //2.验证输入的三个参数是否为空
        if(!StringUtils.hasLength(oldPwd)||!StringUtils.hasLength(newPwd)||!StringUtils.hasLength(rePwd)){//三个参数有一个为空，返回一个错误提示信息
            return Result.error("缺少必须的参数");
        }
        //3.判断原始密码是否正确
        Map<String,Object> map = ThreadLocalUtil.get();
        //从map中取出username
        String username = (String) map.get("username");
        //根据username找到当前登录的用户
        User logUser = userService.findUserByName(username);
        if(!logUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){
            return Result.error("原密码填写不正确");
        }
        //4.新密码和再次输入的是不一致
        if(!rePwd.equals(newPwd)){
            return Result.error("两次填写的新密码不一样");
        }
        userService.updatePwd(newPwd);
        return Result.success();
    }

}
